package com.example.daxiguaforharmony.game;

import com.example.daxiguaforharmony.game.core.*;
import com.example.daxiguaforharmony.game.core.base.DisplayObject;
import com.example.daxiguaforharmony.game.core.base.DisplayObjectContainer;
import com.example.daxiguaforharmony.game.core.base.ITouchCallback;
import com.example.daxiguaforharmony.game.core.component.Button;
import com.example.daxiguaforharmony.game.core.featrue.Featrue;
import com.example.daxiguaforharmony.game.core.game.GameObject;
import com.example.daxiguaforharmony.game.core.game.SceneBase;
import com.example.daxiguaforharmony.game.core.renderers.Label;
import com.example.daxiguaforharmony.game.core.renderers.LabelAtlas;
import com.example.daxiguaforharmony.game.core.renderers.Sprite;
import com.example.daxiguaforharmony.game.core.utils.Callback;
import com.example.daxiguaforharmony.game.core.utils.Log;
import com.example.daxiguaforharmony.game.system.UseDiceSystem;
import com.example.daxiguaforharmony.game.system.UseEyeSystem;
import com.example.daxiguaforharmony.game.system.UseGoldenHammerSystem;
import com.example.daxiguaforharmony.game.system.UseWoodenHammerSystem;
import ohos.agp.render.PixelMapHolder;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;
import org.jbox2d.callbacks.ContactImpulse;
import org.jbox2d.callbacks.ContactListener;
import org.jbox2d.callbacks.QueryCallback;
import org.jbox2d.collision.AABB;
import org.jbox2d.collision.Manifold;
import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.*;
import org.jbox2d.dynamics.contacts.Contact;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class GameScene extends SceneBase implements QueryCallback, ContactListener {
    public interface GameSceneCallback extends GameEvent.GameCallback {
        void onPlayGame();
        void onGameOver(int score);
		void onUpdateScore(int score);
		void onPlayAudio(int audio);
		void onShowToast(String text);
		void onOpenPrivacy();
		void onOpenHelp();
    }
    public static class Event {
        public static String USE_EYE_ITEM = "USE_EYE_ITEM";
        public static String USE_DICE_ITEM = "USE_DICE_ITEM";
        public static String USE_WOODEN_HAMMER_ITEM = "USE_WOODEN_HAMMER_ITEM";
        public static String USE_GOLDEN_HAMMER_ITEM = "USE_GOLDEN_HAMMER_ITEM";
        public static String USE_ITEM = "USE_ITEM";
    }
    public static class ItemID {
        public static int POWER = 1000;
        public static int ITEM1 = 1001;
        public static int ITEM2 = 1002;
        public static int ITEM3 = 1003;
        public static int ITEM4 = 1004;
    }
    //单位是米每平方秒 box2d中所有的距离单位都是米 提供了一个换算比例 PTM_RATIO = 32 意思是一米换算为32个像素
    public static float RATE = 32f;
    public static float PTM_RATIO = 32f;

    public World world; //模拟世界
    public GameData gameData = new GameData();
    private float _timeStep = 1f / 60f; //模拟世界的频率
    private int _velIters = 10; //速率迭代器
    private int _posIters = 10; //迭代次数

    private float _minPosY = 0f;

    private Queue<Fruits> _readyComposeFruits = null;
    private Queue<Fruits> _gameObjectPool = null;

    private Fruits _currFruits = null;
    private LabelAtlas _txtScore = null;
    private Sprite _spLine = null;

    private int _newFuristState = -1;
    private int _fruitsCount = 0;
    private int _score = 0;
    private float _blinkTime = 0f;
    private int _blinkTimes = 0;
    private boolean _isGameOver = true;
    private boolean _touchStart = false;
    private GameSceneCallback _gameCallback = null;
    private Featrue _featrue = new Featrue();

    private int _preRandomFruits = -1;
    private int _previewTimes = 0;
    private Sprite _bgPreviewFruits = null;
    private Sprite _previewFruits = null;
    private Label _txtPreviewNum = null;

    private List<Sprite> crossDeviceScoreBg = null;
    private List<Label> crossDeviceScore = null;

    private DisplayObjectContainer _playGame = null;
    private DisplayObjectContainer _fruitsLayer = null;

    public GameScene(float sceneWidth, float sceneHeight) {
        super(sceneWidth, sceneHeight);
        this._readyComposeFruits = new LinkedList<Fruits>();
        this._gameObjectPool = new LinkedList<Fruits>();
        this._playGame = new DisplayObjectContainer();
        this._fruitsLayer = new DisplayObjectContainer();
        this.crossDeviceScoreBg = new ArrayList<Sprite>();
        this.crossDeviceScore = new ArrayList<Label>();

        this._featrue.AddSystem(new UseEyeSystem(this));
        this._featrue.AddSystem(new UseDiceSystem(this));
        this._featrue.AddSystem(new UseWoodenHammerSystem(this));
        this._featrue.AddSystem(new UseGoldenHammerSystem(this));
        this._featrue.Startup();
    }

    public void AddEvent(String type, Object arg1, Object arg2, Object arg3, Object arg4) {
        this._featrue.AddEvent(type, arg1, arg2, arg3, arg4, null);
    }

    public void setGameCallback(GameSceneCallback gameCallback) {
        this._gameCallback = gameCallback;
    }
    public Fruits getCurrFruits() { return this._currFruits; }

    public void setup() {
        AABB aabb = new AABB();
        aabb.lowerBound.set(-3000f, -3000f);
        aabb.upperBound.set(3000f, 3000f);
        Vec2 gravity = new Vec2(0f, 300.0f / GameScene.RATE);
        this.world = new World(gravity);
        this.world.queryAABB(this, aabb);
        this.world.setContactListener(this);

        PixelMapHolder pixelMapHolder = null;

        pixelMapHolder = AssetManager.getInstance().getFruits("bgdi");
        Sprite bgdi = new Sprite(pixelMapHolder);
        bgdi.scaleX = this._scaleFactor + 0.5f;
        bgdi.scaleY = this._scaleFactor;
        bgdi.x = this._sceneWidth / 2f;
        bgdi.y = this._sceneHeight - bgdi.height * 0.5f;// 0.8f;
        this._container.addChild(bgdi);

        // wall bottom
        this.createShape(bgdi.x, bgdi.y, this._sceneWidth / 2f, bgdi.height * bgdi.scaleY / 2, 100);
        // wall left
        this.createShape(0f, this._sceneHeight / 2f, 4f, this._sceneHeight, 0);
        // wall right
        this.createShape(this._sceneWidth, this._sceneHeight / 2f, 4f, this._sceneHeight, 0);

        this._container.addChild(this._fruitsLayer);

        pixelMapHolder = AssetManager.getInstance().getFruits("num1");
        this._txtScore = new LabelAtlas(pixelMapHolder, 66f, 60f, 60f);
        this._txtScore.text = "0";
        this._txtScore.spacingX = 0f;
        this._txtScore.fontSize = 64f;
        this._txtScore.x = 50f;
        this._txtScore.y = 50f;
        this._container.addChild(this._txtScore);

        pixelMapHolder = AssetManager.getInstance().getFruits("overline1");
        Sprite spLine = new Sprite(pixelMapHolder);
        spLine.scaleX = this._scaleFactor;
        spLine.scaleY = this._scaleFactor;
        spLine.x = this._sceneWidth / 2f;
        spLine.y = 350f - bgdi.height / 2f;
        spLine.visible = true;
        _spLine = spLine;
        this._spLine.visible = true;
        this._container.addChild(spLine);

        this.createItem(1);
        this.createItem(2);
        this.createItem(3);
        this.createItem(4);

        pixelMapHolder = AssetManager.getInstance().getFruits("kuang1");
        this._bgPreviewFruits = new Sprite(pixelMapHolder);
        this._bgPreviewFruits.scaleX = this._scaleFactor;
        this._bgPreviewFruits.scaleY = this._scaleFactor;
        this._bgPreviewFruits.x = this._sceneWidth + 60f;//40
        this._bgPreviewFruits.y = 320f;
        //this._bgPreviewFruits.width = 80;
        this._bgPreviewFruits.visible = true;
        this._container.addChild(this._bgPreviewFruits);

        pixelMapHolder = AssetManager.getInstance().getFruits("f5");//水果
        this._previewFruits = new Sprite(pixelMapHolder);
        this._previewFruits.x = this._sceneWidth - 80f;
        this._previewFruits.y = 320f;
        this._previewFruits.visible = true;
        this._previewFruits.width = 90f;
        this._previewFruits.height = 90f;
        this._container.addChild(this._previewFruits);

        this._txtPreviewNum = new Label();
        this._txtPreviewNum.text = "0";
        this._txtPreviewNum.textSize = 40;
        this._txtPreviewNum.x = this._sceneWidth - 60f;//20
        this._txtPreviewNum.y = 370f;//330
        this._container.addChild(this._txtPreviewNum);

        DisplayObjectContainer container = this._container;
        pixelMapHolder = AssetManager.getInstance().getFruits("kuang1");
        for (int i = 0; i < 5; i++) {
            Sprite bg = new Sprite(pixelMapHolder);
            bg.x = 0f;
            bg.y = 300f + i * 100f;
            bg.scaleX = 1.5f;//背景宽度
            container.addChild(bg);
            Label label1 = new Label();
            label1.text = "";
            label1.textSize = 60;
            label1.x = bg.width * 0.25f;
            label1.y = bg.y;
            container.addChild(label1);
            crossDeviceScoreBg.add(bg);
            crossDeviceScore.add(label1);
            bg.visible = false;
            label1.visible = false;
        }

        pixelMapHolder = AssetManager.getInstance().getFruits("loading_bg");
        Sprite playGameBg = new Sprite(pixelMapHolder);
        playGameBg.x = this._sceneWidth / 2f;
        playGameBg.y = this._sceneHeight / 2f;
        playGameBg.width = this._sceneWidth;
        playGameBg.height = this._sceneHeight;
        this._playGame.addChild(playGameBg);
        Button btnPlayGameBg = new Button(playGameBg);
        this.addTouchHandler(btnPlayGameBg);
        pixelMapHolder = AssetManager.getInstance().getFruits("logo");
        Sprite playGameLogo = new Sprite(pixelMapHolder);
        playGameLogo.x = this._sceneWidth / 2f;
        playGameLogo.y = this._sceneHeight * 0.3f;
        playGameLogo.scaleX = this._scaleFactor;
        playGameLogo.scaleY = this._scaleFactor;
        this._playGame.addChild(playGameLogo);
        pixelMapHolder = AssetManager.getInstance().getFruits("btn_play");
        Sprite imgPlay = new Sprite(pixelMapHolder);
        imgPlay.x = this._sceneWidth / 2f;
        imgPlay.y = this._sceneHeight * 0.7f;
        imgPlay.scaleX = this._scaleFactor;
        imgPlay.scaleY = this._scaleFactor;
        GameScene _self = this;
        Button btnPlay = new Button(imgPlay);
        this.addTouchHandler(btnPlay);
        this._playGame.addChild(imgPlay);
        Label txtPrivacy = new Label();
        txtPrivacy.text = "单击查看隐私协议";
        txtPrivacy.textSize = 55;
        txtPrivacy.x = this._sceneWidth / 2f;
        txtPrivacy.y = this._sceneHeight * 0.9f;
        Button btnPrivacy = new Button(txtPrivacy);
        btnPrivacy.setTouchCallback(new ITouchCallback() {
            @Override
            public void onTouchEvent(TouchEvent touchEvent) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    _self._gameCallback.onOpenPrivacy();
                }
            }
        });
        this.addTouchHandler(btnPrivacy);
        this._playGame.addChild(txtPrivacy);
        pixelMapHolder = AssetManager.getInstance().getFruits("btn_help");
        Sprite imgHelp = new Sprite(pixelMapHolder);
        imgHelp.width = 120;
        imgHelp.height = 120;
        imgHelp.x = 100;
        imgHelp.y = 100;
        this._playGame.addChild(imgHelp);
        Button btnHelp = new Button(imgHelp);
        btnHelp.setTouchCallback(new ITouchCallback() {
            @Override
            public void onTouchEvent(TouchEvent touchEvent) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    _self._gameCallback.onOpenHelp();
                }
            }
        });
        this.addTouchHandler(btnHelp);
        this._container.addChild(this._playGame);
        btnPlay.setTouchCallback(new ITouchCallback() {
            @Override
            public void onTouchEvent(TouchEvent touchEvent) {
                _self._playGame.setVisible(false);
                _self.playGame();
            }
        });
    }

    public DisplayObjectContainer getFruitsLayer() {
        return this._fruitsLayer;
    }

    public void setDeviceScore(int index, String score,boolean isShow) {
        if (index >= 0 && index < this.crossDeviceScore.size()) {
            this.crossDeviceScore.get(index).visible = isShow;
            this.crossDeviceScoreBg.get(index).visible = isShow;
            Label label = this.crossDeviceScore.get(index);
            String text = score + "";
            label.text = text;
            label.textSize = 45;
        }
    }
    public void setVisibleDeviceScore(int index, boolean visible) {
        if (index >= 0 && index < this.crossDeviceScore.size()) {
            this.crossDeviceScore.get(index).visible = visible;
            this.crossDeviceScoreBg.get(index).visible = visible;
        }
    }

    public void hideAllDeviceScore() {
        for (int i = 0; i < 5; i++) {
            this.crossDeviceScore.get(i).visible = false;
            this.crossDeviceScoreBg.get(i).visible = false;
        }
    }
	
	public void startGame() {
		if (this._playGame != null) {
			this._playGame.setVisible(false);
		}
		this.playGame();
	}

    public void playGame() {
        if (this._isGameOver == false) return;
        this._isGameOver = false;
        this._spLine.visible = false;
        this.setScore(0);
        for (int i = 0; i < this._gameObjects.size(); i++) {
            GameObject gameObject = this._gameObjects.get(i);
            if (gameObject instanceof Fruits) {
                Fruits fruits = (Fruits)gameObject;
                this._gameObjectPool.add(fruits);
                fruits.removeFromScene();
            }
        }
        this.createNextFruits();
        if (this._gameCallback != null) {
            this._gameCallback.onPlayGame();
        }
    }

    public void gameOver() {
        if (this._isGameOver == true) return;
        this._isGameOver = true;
        if (this._gameCallback != null) {
            this._gameCallback.onGameOver(this._score);
        }
    }

    public void step() {
        world.step(this._timeStep, this._posIters, this._velIters);
    }

    @Override
    public void update(float dt) {
        super.update(dt);
        if (this._currFruits != null && this._newFuristState == 1) {
            this._currFruits.dropEnd();
			if (this._gameCallback != null) this._gameCallback.onPlayAudio(1);
            this.createNextFruits();
            this._newFuristState = -1;
        }
        if (this._readyComposeFruits.size() > 0) {
            Fruits go1 = this._readyComposeFruits.remove();
            Fruits go2 = this._readyComposeFruits.remove();
            this.readyCompose(go1, go2);
        }
        float minPosY = 0f;
        this._minPosY = this._sceneHeight;
        for (int i = 0; i < this._gameObjects.size(); i++) {
            GameObject gameObject = this._gameObjects.get(i);
            if (gameObject == null || gameObject.enabled == false) continue;
            gameObject.update(dt);
            if (gameObject instanceof Fruits && gameObject.getTag() == 100) {
                Fruits fruits = (Fruits)gameObject;
                minPosY = fruits.getMinPosY();
                if (minPosY < this._minPosY) {
                    this._minPosY = minPosY;
                }
            }
        }
        if (this._isGameOver == false) {
            if (this._minPosY < this._spLine.y) {
                if (this._blinkTime == 0f) {
                    this._spLine.visible = true;
                } else if (this._blinkTime > 0.4f) {
                    this._spLine.visible = true;
                    this._blinkTime = 0f;
                    this._blinkTimes += 1;
                } else if (this._blinkTime > .2f) {
                    this._spLine.visible = false;
                    this._blinkTimes += 1;
                }
                if (this._blinkTimes == 15) {
                    this.gameOver();
                }
                this._blinkTime += dt;
            } else {
                this._spLine.visible = false;
                this._blinkTime = 0f;
                this._blinkTimes = 0;
            }
        }
    }
	
	public void setScore(int score) {
		this._score = score;
		if (this._gameCallback != null) {
			this._gameCallback.onUpdateScore(score);
		}
		this._txtScore.text = this._score + "";
	}

    public int getScore() {
        return this._score;
    }

	public void playAudio(int audio) {
        if (this._gameCallback != null) {
            this._gameCallback.onPlayAudio(audio);
        }
    }

    public void showToast(String text) {
        if (this._gameCallback != null) {
            this._gameCallback.onShowToast(text);
        }
    }

	@Override
    public boolean onTouchEvent(TouchEvent touchEvent) {
        boolean flag = super.onTouchEvent(touchEvent);
        if (flag == true) return true;
        int action = touchEvent.getAction();
        MmiPoint point = touchEvent.getPointerPosition(0);
        if (action == TouchEvent.PRIMARY_POINT_DOWN) {
            this._touchStart = true;
        } else if (action == TouchEvent.POINT_MOVE) {
            if (this._touchStart && this._isGameOver == false && this._currFruits != null && this._currFruits.getTag() == 10000) {
                this._currFruits.updatePositionX(point.getX());
            }
        } else {
            if (this._touchStart && this._isGameOver == false && this._currFruits != null && this._currFruits.getTag() == 10000) {
                this._currFruits.updatePositionX(point.getX());
                this._currFruits.drop();
            }
            this._touchStart = false;
        }
        Log.info("action = " + action);
        return true;
    }

    // =================   ContactListener  =======================

    @Override
    public void beginContact(Contact contact) {
        Body bodyA = contact.m_fixtureA.m_body;
        Body bodyB = contact.m_fixtureB.m_body;

        Fruits goA = null; Fruits goB = null;
        int tagA = 0; int tagB = 0;

        if (bodyA.m_userData instanceof Fruits) {
            goA = (Fruits)bodyA.m_userData;
            tagA = goA.getTag();
        } else tagA = (int)bodyA.m_userData;
        if (bodyB.m_userData instanceof Fruits) {
            goB = (Fruits)bodyB.m_userData;
            tagB = goB.getTag();
        } else tagB = (int)bodyB.m_userData;

        if (tagA == 0 || tagB == 0) return;

        if (tagA == 1000 && tagB == 100 && bodyA.m_type == BodyType.DYNAMIC) {
            if (this._newFuristState == -1) this._newFuristState = 1;
        } else if (tagA == 100 && tagB == 1000 && bodyB.m_type == BodyType.DYNAMIC) {
            if (this._newFuristState == -1) this._newFuristState = 1;
        }
        if (this._currFruits != null && (this._currFruits == goA || this._currFruits == goB)) {
            this._currFruits.setTag(100);
        }

        if (goA != null) tagA = goA.getTag();
        if (goB != null) tagB = goB.getTag();

        if (tagA == 100 && tagB == 100 && goA != null && goB != null) {
            if (goA.getFruitsId() == goB.getFruitsId()
                    && goA.getState() == 0 && goA.getState() == goB.getState()) {
                goA.setState(1); goB.setState(1);
                this._readyComposeFruits.add(goA);
                this._readyComposeFruits.add(goB);
            }
        }
    }

    @Override
    public void endContact(Contact contact) {
    }

    @Override
    public void preSolve(Contact contact, Manifold manifold) {
    }

    @Override
    public void postSolve(Contact contact, ContactImpulse contactImpulse) {
    }

    // =================   Body Method  =======================

    public Body createShape(float x, float y, float width, float height, Object userData) {
        PolygonShape shape = new PolygonShape();
        shape.setAsBox(width / GameScene.RATE, height / GameScene.RATE);
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyType.STATIC;
        bodyDef.gravityScale = 1f;
        bodyDef.userData = userData;

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = shape;
        fixtureDef.density = 1f;
        fixtureDef.friction = 1f;
        fixtureDef.restitution = 0f;
        fixtureDef.userData = null;

        bodyDef.position.set(x / GameScene.RATE, y / GameScene.RATE);
        Body bod = world.createBody(bodyDef);
        bod.createFixture(fixtureDef);

        return bod;
    }

    public Body createCircle(float x, float y, float radius) {
        BodyDef bodyDef = new BodyDef();//刚体参数（刚体）
        bodyDef.position.set(x / GameScene.RATE, y / GameScene.RATE);//位置
        bodyDef.angle = 0;//角度
        bodyDef.linearVelocity = new Vec2(0f, 100f / GameScene.RATE);//线性速度y900f
        bodyDef.angularVelocity = 0f;//角速度0f
        bodyDef.fixedRotation = false;//固定角度
        bodyDef.active = true;//激活
        bodyDef.bullet = false;//子弹
        bodyDef.allowSleep = true;//允许休息true
        bodyDef.gravityScale = 3.0f;//重力比例,级别3.0f
        bodyDef.linearDamping = 0.3f;//线性减震0.0f
        bodyDef.angularDamping = 0f;//角减震0.0f
        bodyDef.userData = null;//使用者属性
        bodyDef.type = BodyType.STATIC; // BodyType.DYNAMIC;//刚体模式 定义动态的刚体

        CircleShape shape = new CircleShape();
        shape.setRadius(radius / GameScene.RATE);

        FixtureDef fixtureDef = new FixtureDef();//Fixture参数（夹具）
        fixtureDef.shape = shape;//形状
        fixtureDef.userData = null;//使用者属性
        fixtureDef.friction = 1f;//摩擦系数1
        fixtureDef.restitution = 0.05f;//补偿系数 能量损失率 恢复.1
        fixtureDef.density = 1f;//密度1
        fixtureDef.isSensor = false;//传感器

        Body body = world.createBody(bodyDef);
        body.createFixture(fixtureDef);

        return body;
    }

    // =================   Fruits Method  =======================

    public void readyCompose(Fruits target, Fruits source) {
        DisplayObject targetDis = target.getDisplayObject();
        DisplayObject sourceDis = source.getDisplayObject();
        if (targetDis.y < sourceDis.y) {
            Fruits temp = target;
            target = source;
            source = temp;
            targetDis = target.getDisplayObject();
            sourceDis = source.getDisplayObject();
        }
        int fruitsId = target.getFruitsId() + 1;
        String resFruitsId = "f" + fruitsId;
        PixelMapHolder pixelMapHolder = AssetManager.getInstance().getFruits(resFruitsId);
        if (pixelMapHolder != null) {
            GameScene self = this;
            Fruits finalSource = source;
            Fruits finalTarget = target;
            DisplayObject finalTargetDis = targetDis;
            target.idle();
            DisplayObjectContainer parent = sourceDis.getParent();
            parent.setChildIndex(sourceDis, parent.children.size());
            source.moveTo(0.1f, targetDis.x, targetDis.y, new Callback.CompleteCallback() {
                @Override
                public void complete() {
                    Fruits gameObject = self.createNewFruits(fruitsId);
                    gameObject.setPosition(finalTargetDis.x, finalTargetDis.y);
                    gameObject.dropEnd();
                    float width = finalTargetDis.width * finalTargetDis.scaleX;
                    FruitsEffect.playEffect(fruitsId - 1, finalTargetDis.x, finalTargetDis.y, width, self);
                    finalSource.removeFromScene();
                    finalTarget.removeFromScene();
                    self._gameObjectPool.add(finalSource);
                    self._gameObjectPool.add(finalTarget);
                    if (self._gameCallback != null) self._gameCallback.onPlayAudio(2);
                    int score = self._score + fruitsId;
                    self.setScore(score);
                }
            });
        } else {
            target.setState(0);
            source.setState(0);
        }
    }

    public List<FruitsVO> getFruitsList() {
        List<FruitsVO> volist = new ArrayList<>();
        for (int i = 0; i < this._gameObjects.size(); i++) {
            Fruits f = (Fruits)this._gameObjects.get(i);
            FruitsVO vo = new FruitsVO();
            vo.fruitsId = f.getFruitsId();
            vo.state = f.getState();
            vo.tag = f.getTag();
            vo.x = f.getDisplayObject().x;
            vo.y = f.getDisplayObject().y;
            volist.add(vo);
        }
        return volist;
    }

    public void revertFruitsList(List<FruitsVO> fruitsList) {
        Fruits currFruits = null;
        for (int i = 0; i < fruitsList.size(); i++) {
            FruitsVO f = fruitsList.get(i);
            Fruits fruits = this.createNewFruits(f.fruitsId);
            fruits.setState(f.state);
            fruits.setPosition(f.x, f.y);
            int tag = f.tag;
            if (tag == 10000) fruits.born();
            else if (tag == 1000) fruits.drop();
            else if (tag == 100) fruits.dropEnd();
            if (tag == 10000) {
                currFruits = fruits;
            }
        }
        this._fruitsCount = fruitsList.size();
        if (currFruits != null) {
            if (this._currFruits != null) {
                Fruits f = this._currFruits;
                f.removeFromScene();
                this._gameObjectPool.add(f);
            }
            this._currFruits = currFruits;
        }
    }

    public void createNextFruits() {
        int fruitsId = this._preRandomFruits;
        if (fruitsId == -1) fruitsId = ranomFruitsId();
        Fruits gameObject = this.createNewFruits(fruitsId);
        gameObject.born();
        this._currFruits = gameObject;
        if (this._preRandomFruits > 0) {
            this._preRandomFruits = -1;
        } else {
            this._fruitsCount += 1;
        }
        this.showPreRandomFruits();
    }

    public Fruits createNewFruits(int fruitsId) {
        String resFruitsId = "f" + fruitsId;
        PixelMapHolder pixelMapHolder = AssetManager.getInstance().getFruits(resFruitsId);
        Fruits gameObject = null;
        if (this._gameObjectPool.size() > 0) {
            gameObject = this._gameObjectPool.remove();
        }
        // Sprite sprite1 = new Sprite(pixelMapHolder);
        // Fruits gameObject1 = new Fruits(this, sprite1);
        if (gameObject == null) {
            Sprite sprite = new Sprite(pixelMapHolder);
            gameObject = new Fruits(this, sprite);
        } else {
            DisplayObject displayObject = gameObject.getDisplayObject();
            if (displayObject instanceof Sprite) {
                Sprite sprite = (Sprite)displayObject;
                sprite.replacePixelMapHolder(pixelMapHolder);
            }
            gameObject.reset();
        }
        gameObject.setFruitsId(fruitsId);
        gameObject.addToScene();
        return gameObject;
    }

    public void addPreviewTimes(int addNum) {
        this._previewTimes += addNum;
        if (this._preRandomFruits <= -1) {
            this.showPreRandomFruits();
        } else {
            this._txtPreviewNum.text = this._previewTimes + "";
        }
    }

    public void showPreRandomFruits() {
        if (this._previewTimes > 0) {
            this._previewTimes -= 1;
            this._previewFruits.visible = true;
            this._bgPreviewFruits.visible = true;
            this._txtPreviewNum.visible = true;
            this._preRandomFruits = this.ranomFruitsId();
            this._fruitsCount += 1;
            String resFruitsId = "f" + this._preRandomFruits;
            PixelMapHolder pixelMapHolder = AssetManager.getInstance().getFruits(resFruitsId);
            this._previewFruits.replacePixelMapHolder(pixelMapHolder);
            this._previewFruits.width = 90f;
            this._previewFruits.height = 90f;
        } else {
            this._previewTimes = 0;
            this._previewFruits.visible = false;
            this._bgPreviewFruits.visible = false;
            this._txtPreviewNum.visible = false;
        }
        this._txtPreviewNum.text = this._previewTimes + "";
    }

    public void pushInFruitsPool(Fruits fruits) {
        if (!this._gameObjectPool.contains(fruits)) {
            this._gameObjectPool.add(fruits);
            fruits.removeFromScene();
        }
    }

    private int ranomFruitsId() {
        int index = 0;
        if (this._fruitsCount == 0 || this._fruitsCount == 1) index = 0;
        if (this._fruitsCount == 2) index = 1;
        if (this._fruitsCount == 3 || this._fruitsCount == 4) index = 2;
        if (this._fruitsCount == 5) index = 3;
        if (this._fruitsCount > 5) index = (int)(Math.random() * 5);
        return index + 1;
    }

    // =================   HUD  =======================

    public void createItem(int index) {
        GameScene _self = this;
        // float offsetX = (this._sceneWidth - 120f * 4 * this._scaleFactor) / 2f;
        // offsetX += offsetX + 120f * this._scaleFactor * (index - 1 + 0.5f);
        // float offsetY = this._sceneHeight - item1.height;
        float offsetX = this._sceneWidth - 120f;
        float offsetY = this._sceneHeight / 2f - 120f * 2 * this._scaleFactor;
        PixelMapHolder pixelMapHolder = AssetManager.getInstance().getFruits("item100" + index);
        Sprite sp = new Sprite(pixelMapHolder);
        sp.x = offsetX;
        sp.y = offsetY + 120f * this._scaleFactor * (index - 1 + 0.5f);
        sp.scaleX = this._scaleFactor * 1.3f;
        sp.scaleY = this._scaleFactor * 1.3f;
        this._container.addChild(sp);
        Button item1 = new Button(sp);
        this.addTouchHandler(item1);
        final int _itemId = 1000 + index;
        item1.setTouchCallback(new ITouchCallback() {
            public int itemId = _itemId;
            @Override
            public void onTouchEvent(TouchEvent touchEvent) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    System.out.println("onTouchEvent itemId==="+this.itemId);
                    if (this.itemId == ItemID.ITEM1) {
                        _self._featrue.AddEvent(Event.USE_EYE_ITEM, null);
                    } else if (this.itemId == ItemID.ITEM2) {
                        _self._featrue.AddEvent(Event.USE_DICE_ITEM, null);
                    } else if (this.itemId == ItemID.ITEM3) {
                        _self._featrue.AddEvent(Event.USE_WOODEN_HAMMER_ITEM, null);
                    } else if (this.itemId == ItemID.ITEM4) {
                        _self._featrue.AddEvent(Event.USE_GOLDEN_HAMMER_ITEM, null);
                    }
                }
            }
        });
    }

    // =================   QueryCallback  =======================

    public boolean reportFixture(Fixture fixture) {
        return false;
    }

}
